package com.zjy.weather.util

import android.content.Context
import android.text.TextUtils
import android.util.Log

import com.jakewharton.disklrucache.DiskLruCache
import com.zjy.weather.BuildConfig

import java.io.BufferedOutputStream
import java.io.BufferedReader
import java.io.IOException
import java.io.InputStream
import java.io.InputStreamReader

/**
 * Created by wiikii on 16/12/6.
 * Copyright (C) 2014 wiikii. All rights reserved.
 */
class DiskStringCache private constructor(context: Context) {
    private var mDiskLruCache: DiskLruCache? = null

    init {
        try {
            mDiskLruCache = DiskLruCache.open(SystemUtils.getDiskCacheDir(context, CACHE_DIR_NAME),
                    SystemUtils.getVersionCode(context), 1, 2 * 1024 * 1024L)
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }

    companion object {
        val BUFFER_SIZE = 8 * 1024
        val CACHE_DIR_NAME = "information"

        var _INSTANCE: DiskStringCache? = null

        private fun getInstance(context: Context): DiskStringCache {
            if (_INSTANCE == null) {
                synchronized(DiskStringCache::class.java) {
                    if (_INSTANCE == null) {
                        _INSTANCE = DiskStringCache(context)
                    }
                }
            }
            return _INSTANCE!!
        }

        fun getString(context: Context?, key: String): String? {
            context?.let {
                if (!key.isNullOrEmpty()) {
                    return getInstance(context).getString(key)
                }
            }
            return null
        }

        fun putString(context: Context?, key: String, value: String) {
            context?.let {
                getInstance(it).putString(key, value)
            }
        }
    }

    private fun convertStreamToString(`is`: InputStream): String {
        val reader = BufferedReader(InputStreamReader(`is`))
        return reader.readText()
    }

    private fun getString(key: String): String? {
        if (TextUtils.isEmpty(key) || mDiskLruCache == null) {
            return null
        }

        var snapshot: DiskLruCache.Snapshot? = null
        try {
            snapshot = mDiskLruCache!!.get(key)
            if (snapshot == null) {
                return null
            }

            val inputStream = snapshot.getInputStream(0)
            if (inputStream != null) {
                val value = convertStreamToString(inputStream)
                if (BuildConfig.DEBUG) {
                    Log.e("DiskStringCache", "getString(): key=$key, value=$value")
                }
                return value
            }

        } catch (e: IOException) {
            e.printStackTrace()
        } finally {
            SystemUtils.closeStream(snapshot)
        }

        return null
    }

    private fun writeStringToFile(string: String, editor: DiskLruCache.Editor?): Boolean {
        if (TextUtils.isEmpty(string) || editor == null) {
            return false
        }

        var bufferedOutputStream: BufferedOutputStream? = null
        try {
            bufferedOutputStream = BufferedOutputStream(editor.newOutputStream(0), BUFFER_SIZE)
            bufferedOutputStream.write(string.toByteArray())
            return true
        } catch (e: IOException) {
            return false
        } finally {
            SystemUtils.closeStream(bufferedOutputStream)
        }
    }

    private fun putString(key: String, value: String) {
        mDiskLruCache?.let {
            if (key.isNullOrEmpty() || value.isNullOrEmpty()) {
                Log.e("DiskStringCache", "putString(): key or value is null")
            } else {
                var editor: DiskLruCache.Editor? = it.edit(key)
                editor?.let {
                    try {
                        if (writeStringToFile(value, it)) {
                            it.commit()
                            Log.e("DiskStringCache", "putString(): success")
                            it.abort()
                        } else {
                            Log.e("DiskStringCache", "putString(): failed")
                        }
                    } catch (e: Exception) {
                        Log.e("DiskStringCache", "putString(): failed")
                    }
                }
            }
        } ?: let {
            if (BuildConfig.DEBUG) {
                Log.e("DiskStringCache", "putString(): disk cache is null")
            }
        }
    }


}
